package com.pengke.pangu.controller.sys;

import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.secure.BCrypt;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.captcha.generator.RandomGenerator;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.pengke.pangu.common.config.ConstConfig;
import com.pengke.pangu.common.enums.ResultCode;
import com.pengke.pangu.common.utils.R;
import com.pengke.pangu.common.utils.RedisUtil;
import com.pengke.pangu.dto.LoginUser;
import com.pengke.pangu.service.sys.entity.SysPermission;
import com.pengke.pangu.service.sys.entity.SysRole;
import com.pengke.pangu.service.sys.entity.SysUser;
import com.pengke.pangu.service.sys.service.ISysPermissionService;
import com.pengke.pangu.service.sys.service.ISysRoleService;
import com.pengke.pangu.service.sys.service.ISysUserService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Slf4j
@RestController
public class LoginController {

    @Resource
    private ISysUserService sysUserService;

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private ISysPermissionService sysPermissionService;

    @Resource
    private ISysRoleService sysRoleService;

    @PostMapping("/login")
    public R login(@RequestBody LoginUser loginUser) {

        //验证码判断逻辑
        if (ObjUtil.isNotNull(loginUser) && StrUtil.isNotEmpty(loginUser.getCaptcha()) && StrUtil.isNotEmpty(loginUser.getCaptchaId())) {
            //判断提交的验证码和缓存中的验证码
            String captchaRedis = redisUtil.getCacheObject(loginUser.getCaptchaId());
            if (StrUtil.isEmpty(captchaRedis)) {
                return R.fail(ResultCode.CAPTCHAEXPIRATION);
            }

            if (!loginUser.getCaptcha().equalsIgnoreCase(captchaRedis)) {
                return R.fail(ResultCode.BADCAPTCHA);
            }
        } else {
            return R.fail(ResultCode.BADCAPTCHA);
        }

        //查询数据库用户信息
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("account", loginUser.getAccount());
        SysUser sysUser = sysUserService.getOne(queryWrapper);

//        if (ObjectUtil.isNotNull(sysUser) && ) {
        if (ObjectUtil.isNotNull(sysUser)) {
            //查询到用户并验证密码正确
            if (sysUser.getLocked() == 1) {
                return R.fail(ResultCode.LOCKED);
            }

            if (sysUser.getDisabled() == 1) {
                return R.fail(ResultCode.DISABLED);
            }

            if (BCrypt.checkpw(loginUser.getPassword(), sysUser.getPassword())) {
                //登录成功
                StpUtil.login(sysUser.getId());

                //清除登录失败次数
                redisUtil.deleteObject(sysUser.getAccount() + ":login_fail_count");

                //获取用户角色和权限信息
                Map<String, Object> param = new HashMap<String, Object>();
                param.put("id", sysUser.getId());
                List<SysPermission> sysPermissionList = sysPermissionService.getSysPermissionByUserId(param);
                List<String> permissionList = null;
                if (!sysPermissionList.isEmpty()) {
                    permissionList = new ArrayList<>();
                    for (SysPermission sysPermission : sysPermissionList) {
                        permissionList.add(sysPermission.getPermissionCode());
                    }
                }

                List<SysRole> sysRoleList = sysRoleService.getRoleByUserId(sysUser.getId());
                List<String> roleList = null;
                if (!sysRoleList.isEmpty()) {
                    roleList = new ArrayList<>();
                    for (SysRole sysRole : sysRoleList) {
                        roleList.add(sysRole.getRoleCode());
                    }
                }

                //组装返回对象
                Map<String, Object> resultMap = new HashMap<>();
                resultMap.put("userInfo", sysUser);
                resultMap.put("roleList", roleList);
                resultMap.put("permissionList", permissionList);
                resultMap.put("token", StpUtil.getTokenValue());

                //加载用户信息
                return R.ok(resultMap);
            } else {
                //todo 处理失败登录次数，设置账户锁定
                //密码错误,获取登录次数
                Integer count = redisUtil.getCacheObject(sysUser.getAccount() + ":login_fail_count");
                if (ObjUtil.isNull(count)) {
                    count = 0;
                }
                if (count < ConstConfig.USER_LOGIN_COUNT - 1) {
                    redisUtil.setCacheObject(sysUser.getAccount() + ":login_fail_count", ++count, ConstConfig.USER_LOCKED_TIME, TimeUnit.MINUTES);
                    return R.fail(ResultCode.ERROR, "账号密码不正确！还可以尝试登录:" + (ConstConfig.USER_LOGIN_COUNT - count) + "次！");
                } else {
                    sysUserService.update(null, Wrappers.<SysUser>lambdaUpdate()
                            .set(SysUser::getLocked, 1)
                            .eq(SysUser::getId, sysUser.getId())
                    );

                    //todo 发送延时任务，15分钟之后设置账户解锁状态

                    return R.fail(ResultCode.LOCKED);
                }
            }
        } else {
            return R.fail(ResultCode.ERROR, "账号不存在！");
        }

    }

    // 查询登录状态
    @GetMapping("/isLogin")
    @SaCheckLogin
    public R isLogin() {
        return R.ok("是否登录：" + StpUtil.isLogin());
    }

    // 注销登录
    @GetMapping("/logout")
    public R logout() {
        StpUtil.logout();
        return R.ok();
    }

    @GetMapping("/captcha")
    public R captcha() {

        RandomGenerator randomGenerator = new RandomGenerator(ConstConfig.CAPTCHA_RANDOMWORDS, ConstConfig.CAPTCHA_LENGTH);
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(ConstConfig.CAPTCHA_WIDTH, ConstConfig.CAPTCHA_HEIGHT);
        lineCaptcha.setGenerator(randomGenerator);
        lineCaptcha.createCode();

        String captchaCode = lineCaptcha.getCode();
        String captchaUUID = IdUtil.simpleUUID();

        log.info("验证码：{},验证码ID：{}", captchaCode, captchaUUID);

        //UUID，code 存入缓存
        redisUtil.setCacheObject(captchaUUID, captchaCode, ConstConfig.CAPTCHA_EXPIRATIONTIME, TimeUnit.MINUTES);

        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("captchaId", captchaUUID);
        resultMap.put("captchaImg", lineCaptcha.getImageBase64Data());

        return R.ok(resultMap);
    }

    @GetMapping("/401")
    public R get401() {
        return R.fail(ResultCode.UNAUTHORIZED);
    }

    @GetMapping("/500")
    public R get500() {
        return R.fail(ResultCode.ERROR);
    }

    @GetMapping("/200")
    public R get200() {
        return R.ok();
    }

}